package com.jiashihui.schema_lgorithm.java.properties.util;

import java.util.ArrayList;
import java.util.List;

public class PropertiesContext {

    private static final String specialSaveChars = "=: \t\r\n\f#!";
    private static final char[] hexDigit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    /**
     * 文件所有的行信息
     */
    private List<Object> commentOrEntrys = new ArrayList<Object>();

    public List<Object> getCommentOrEntrys() {
        return commentOrEntrys;
    }

    /**
     * @param line 添加一行信息
     */
    public void addCommentLine(String line) {
        commentOrEntrys.add(line);
    }

    public void putOrUpdate(PropertyEntry pe) {
        remove(pe.getKey());
        commentOrEntrys.add(pe);
    }

    public void putOrUpdate(String key, String value, String line) {
        PropertyEntry pe = new PropertyEntry(key, value, line);
        remove(key);
        commentOrEntrys.add(pe);
    }

    public void putOrUpdate(String key, String value) {
        PropertyEntry pe = new PropertyEntry(key, value);
        int index = remove(key);
        commentOrEntrys.add(index, pe);
    }

    public int remove(String key) {
        for (int index = 0; index < commentOrEntrys.size(); index++) {
            Object obj = commentOrEntrys.get(index);
            if (obj instanceof PropertyEntry && key.equals(((PropertyEntry) obj).getKey())) {
                commentOrEntrys.remove(obj);
                return index;
            }
        }
        return commentOrEntrys.size();
    }

    /**
     * @author P00606
     * <p>
     * Property 的 Entry 类
     */
    class PropertyEntry {

        private String key;

        private String value;

        private String line;

        public String getLine() {
            return line;
        }

        public void setLine(String line) {
            this.line = line;
        }

        public PropertyEntry(String key, String value) {
            this.key = key;
            this.value = value;
        }

        /**
         * @param key
         * @param value
         * @param line
         */
        public PropertyEntry(String key, String value, String line) {
            this(key, value);
            this.line = line;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        @Override
        public String toString() {
            if (line != null) {
                return line;
            }
            if (key != null && value != null) {
                String k = saveConvert(key, true);
                String v = saveConvert(value, false);
                return k + "=" + v;
            }
            return null;
        }

        private String saveConvert(String theString, boolean escapeSpace) {
            int len = theString.length();
            StringBuffer outBuffer = new StringBuffer(len * 2);
            for (int x = 0; x < len; x++) {
                char aChar = theString.charAt(x);
                switch (aChar) {
                    case ' ':
                        if (x == 0 || escapeSpace) {
                            outBuffer.append('\\');
                        }
                        outBuffer.append(' ');
                        break;
                    case '\\':
                        outBuffer.append('\\');
                        outBuffer.append('\\');
                        break;
                    case '\t':
                        outBuffer.append('\\');
                        outBuffer.append('t');
                        break;
                    case '\n':
                        outBuffer.append('\\');
                        outBuffer.append('n');
                        break;
                    case '\r':
                        outBuffer.append('\\');
                        outBuffer.append('r');
                        break;
                    case '\f':
                        outBuffer.append('\\');
                        outBuffer.append('f');
                        break;
                    default:
                        if ((aChar < 0x0020) || (aChar > 0x007e)) {
                            outBuffer.append('\\');
                            outBuffer.append('u');
                            outBuffer.append(toHex((aChar >> 12) & 0xF));
                            outBuffer.append(toHex((aChar >> 8) & 0xF));
                            outBuffer.append(toHex((aChar >> 4) & 0xF));
                            outBuffer.append(toHex(aChar & 0xF));
                        } else {
//                            if (specialSaveChars.indexOf(aChar) != -1) {
//                                outBuffer.append('\\');
//                            }
                            outBuffer.append(aChar);
                        }
                }
            }
            return outBuffer.toString();
        }

        /**
         * Convert a nibble to a hex character
         *
         * @param nibble the nibble to convert.
         */
        private char toHex(int nibble) {
            return hexDigit[(nibble & 0xF)];
        }
    }
}
